#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include "dfx.h"

#define DEVICE_NAME "dfx"
#define CLASS_NAME "dfx"


static struct class *dfx;
static dev_t devt;
static struct cdev dfx_cdev;


static int dfx_open(struct inode *inode, struct file *file) {
    return 0;
}

static int dfx_release(struct inode *inode, struct file *file) {
    return 0;
}

static long dfx_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
    return 0;
}

static struct file_operations fops = {
    .open = dfx_open,
    .release = dfx_release,
    .unlocked_ioctl = dfx_ioctl,
};

static int __init dfx_init(void) {
    int ret;

    // 动态分配设备号
    ret = alloc_chrdev_region(&devt, 0, 1, DEVICE_NAME);
    if (ret < 0) {
        pr_err("Failed to allocate device number\n");
        return ret;
    }

    // 初始化并添加字符设备
    cdev_init(&dfx_cdev, &fops);
    ret = cdev_add(&dfx_cdev, devt, 1);
    if (ret < 0) {
        pr_err("Failed to add cdev\n");
        goto err_cdev;
    }

    // 创建设备类
    dfx = class_create(THIS_MODULE, CLASS_NAME);
    if (IS_ERR(dfx)) {
        ret = PTR_ERR(dfx);
        pr_err("Failed to create class\n");
        goto err_class;
    }

    // 创建设备节点
    if (IS_ERR(device_create(dfx, NULL, devt, NULL, DEVICE_NAME))) {
        pr_err("Failed to create device\n");
        ret = -1;
        goto err_device;
    }

    pr_info("Driver loaded\n");
    return 0;

err_device:
    class_destroy(dfx);
err_class:
    cdev_del(&dfx_cdev);
err_cdev:
    unregister_chrdev_region(devt, 1);
    return ret;
}

static void __exit dfx_exit(void) {
    device_destroy(dfx, devt);
    class_destroy(dfx);
    cdev_del(&dfx_cdev);
    unregister_chrdev_region(devt, 1);
    pr_info("Driver unloaded\n");
}

module_init(dfx_init);
module_exit(dfx_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("openUBMC-qemu");